package com.googlecode.kipler.container.dl;

import java.util.Iterator;
import java.util.Set;

import com.googlecode.kipler.container.generic.MultivalueHashMap;
import com.googlecode.kipler.syntax.concept.BooleanConcept;
import com.googlecode.kipler.syntax.concept.BooleanConstructor;
import com.googlecode.kipler.syntax.concept.Concept;
import com.googlecode.kipler.syntax.concept.ConceptName;
import com.googlecode.kipler.syntax.concept.InequalityConstructor;
import com.googlecode.kipler.syntax.concept.NaryBooleanConcept;
import com.googlecode.kipler.syntax.concept.Nominal;
import com.googlecode.kipler.syntax.concept.QualifiedNoRestriction;
import com.googlecode.kipler.syntax.concept.RoleQuantification;

/**
 * 
 * @author İnanç Seylan
 * 
 */
public class Individual {
	private String name;

	private MultivalueHashMap<ConceptCategory, Concept> library = new MultivalueHashMap<ConceptCategory, Concept>();

	private ConceptCategory findCategory(Concept desc) {
		ConceptCategory result = null;
		if (desc instanceof ConceptName) {
			result = ConceptCategory.ATOMIC;
		} else if (desc instanceof BooleanConcept) {
			BooleanConcept bd = (BooleanConcept) desc;
			result = (bd.getConstructor() == BooleanConstructor.INTERSECTION) ? ConceptCategory.INTERSECTION
					: ConceptCategory.UNION;
		} else if (desc instanceof NaryBooleanConcept) {
			NaryBooleanConcept bc = (NaryBooleanConcept) desc;
			result = (bc.getConstructor() == BooleanConstructor.INTERSECTION) ? ConceptCategory.NARY_INTERSECTION
					: ConceptCategory.NARY_UNION;
		} else if (desc instanceof RoleQuantification) {
			RoleQuantification rq = (RoleQuantification) desc;
			result = (rq.getConstructor() == RoleQuantification.Constructor.ALL) ? ConceptCategory.ALL
					: ConceptCategory.SOME;
		} else if (desc instanceof QualifiedNoRestriction) {
			QualifiedNoRestriction qr = (QualifiedNoRestriction) desc;
			result = (qr.getConstructor() == InequalityConstructor.AT_MOST) ? ConceptCategory.AT_MOST
					: ConceptCategory.AT_LEAST;
		} else if (desc instanceof Nominal) {
			result = ConceptCategory.NOMINAL;
		}
		return result;
	}

	public Individual() {
		// adding the following results in problems with the interpolating
		// calculus.
		// add(ConceptName.topConcept());
	}

	public Individual(String name) {
		setName(name);
		// add(ConceptName.topConcept());
	}

	public Set<Concept> getConcepts() {
		return library.values();
	}

	public Set<Concept> getConcepts(ConceptCategory category) {
		return library.getValuesForKey(category);
	}

	public String getName() {
		return name.toString();
	}

	public void setName(String name) {
		this.name = name;
	}

	public Individual copy() {
		Individual node = new Individual();
		node.name = name;
		node.library = (MultivalueHashMap<ConceptCategory, Concept>) this.library
				.copy();
		return node;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj != null && (obj.getClass().equals(this.getClass()))) {
			Individual other = (Individual) obj;
			return name.equals(other.name) && library.equals(other.library);
		}
		return false;
	}

	@Override
	public int hashCode() {
		return 17 * 37 + name.hashCode();
	}

	public void add(Concept concept) {
		ConceptCategory cat = findCategory(concept);
		library.put(cat, concept);
	}

	public boolean contains(Concept concept) {
		ConceptCategory cat = findCategory(concept);
		return library.containsKeyValue(cat, concept);
	}

	public boolean containsAllConceptsOf(Individual other) {
		boolean result = library.keySet().containsAll(other.library.keySet());
		Iterator<ConceptCategory> i = other.library.keySet().iterator();
		while (result && i.hasNext()) {
			ConceptCategory category = i.next();
			result = result
					&& library.getValuesForKey(category).containsAll(
							other.library.getValuesForKey(category));
		}
		return result;
	}

	public boolean hasSameConceptsAs(Individual other) {
		boolean result = library.keySet().equals(other.library.keySet());
		Iterator<ConceptCategory> i = other.library.keySet().iterator();
		while (result && i.hasNext()) {
			ConceptCategory category = i.next();
			result = result
					&& library.getValuesForKey(category).equals(
							other.library.getValuesForKey(category));
		}
		return result;
	}

	@Override
	public String toString() {
		return name + ":" + getConcepts();
	}

}
